import router from './router' // js文件里面不能使用 thsi.$router
import store from '@/store' // js文件里面不能使用 thsi.$store
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import getPageTitle from '@/utils/get-page-title'
import { getToken } from '@/utils/auth'
import { profileRequest } from '@/api/user'
import { asyncRoutes } from '@/router'

NProgress.configure({ showSpinner: false })

// 有一个白名单
const whiteList = ['/login']

// 路由守卫，进入路由
router.beforeEach(async(to, from, next) => {
  const token = getToken()
  // 虚拟进度条开启
  NProgress.start()

  document.title = getPageTitle(to.meta.title)

  // next()

  // 不管有什么方式，只要路由跳转了，就应该做一个验证
  // 1. 有token 表示用户登录过了，访问任何页面直接放行1111
  if (token) {
    // 如果有token，就证明的登录过了，那如果在强行去访问登录界面， 还能去
    NProgress.done()
    if (to.path === '/login') {
      next('/')
    } else {
      // 有token 登录过了，想访问其他的需要权限的页面，就会走这个if分支
      // 下面的if语句，就是为了在切换路由的时候，如果请求以后发送过了，那么切换其他路由就不要在发请求，优化代码
      // if (!store.state.user.userInfo.userId) {
      if (!store.getters.userId) {
        // 在这里发起获取用户信息的接口比较合适
        const res = await profileRequest()
        // console.log(res)
        // 在vue组件里面才能使用 this.$store
        // this.$store.commit('user/setUserInfoMutation', res.data)
        // 在js文件里面，需要手动导入 store这个实例对象
        store.commit('user/setUserInfoMutation', res.data)

        // res.data.roles.menus 这个数组是当前 员工所拥有的权限标识 组成的数组
        console.log(res.data.roles.menus, asyncRoutes)
        const filterRoutes = asyncRoutes.filter(item => {
          // return true
          // 这个代码就是说， 从所有动态路由数组里面，根据后端返回的当前员工拥有的权限，过滤筛选出来
          // 当前员工能够看到哪几个动态路由，过滤筛选以下，最后将过滤筛选后的路由对象，添加到路由实例里面去
          return res.data.roles.menus.includes(item.name)
        })
        // 将得到的动态路由数组， 加入到vuex里面去
        store.commit('user/setRoutes', filterRoutes)
        console.log(filterRoutes)
        // addRoutes这个是vue-router这个库 提供的专门用来动态添加的方法， 参数就是路由实例对象组成的数组
        // 兜底的路由一定要放在所有路由最后面，意思就是 当所有静态 动态路由都匹配不到的时候，就匹配*号，跳转到404页面
        router.addRoutes([...filterRoutes, { path: '*', redirect: '/404', hidden: true }])
        // 下面这个next必须写上to.path， 就是动态路由跳转的时候，要手动告诉路径
        next(to.path)
      } else {
        next()
      }
    }
    return
  }

  // 只要走到了这里，就说明一定没有token
  // 如果没有token，那么直接跳转回登录页面
  // next('/login')  // 直接写这个next的时候，就会出现栈溢出的问题， 就是这个路由守卫函数 调用了多次
  // 英文单词就是 maxium  call stack 调用栈超过最大次数了
  if (whiteList.includes(to.path)) {
    next()
    NProgress.done()
    return
  }

  next('/login') // 这句话是强行将要过去的路由，跳转到另外一个路由，之前跳转的路由就不会走 afterEach 路由守卫
  NProgress.done()
})

// 路由守卫，进入路由成功以后， 一般只需要写这两个钩子函数
router.afterEach(() => {
  // 虚拟进度条结束
  NProgress.done()
})
